home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / cuj1008.zip / 1008083A < prev    next >
Text File  |  1991-12-04  |  6KB  |  173 lines

  1. // refptr.hpp - Macros for RefCntPtrs
  2. //   These macros simplify the process of
  3. // creating a new reference count pointer
  4. // class for a new class type - instead of
  5. // copying an existing one and changing the
  6. // names with a text editor, the
  7. // preprocessor is used to substitute the
  8. // appropriate names.  This is basically an
  9. // attempt to emulate class templates, until
  10. // C++ compilers that implement templates
  11. // are available.
  12. //
  13. //   There are two primary macros here - the
  14. // first is the DECLARE macro, for the class
  15. // declaration and inline functions, i.e.
  16. // the stuff usually found in the ".hpp"
  17. // file.  The DEFINE macro contains the
  18. // definition of the non-inline member
  19. // functions - the stuff usually found in
  20. // the ".cpp" file.
  21. //
  22. //   To use these, simply create a class
  23. // derived from RefCntItem, then put a
  24. // RefCntPtrDECLARE() in an appropriate
  25. // header file and a RefCntPtrDEFINE() in
  26. // appropriate definition file (the class
  27. // name is substituted for 'type').
  28.  
  29. #ifndef RefCntPtr_MACROS
  30.  #define RefCntPtr_MACROS
  31.  
  32.  // this is used to create a name for
  33.  // the class being defined, by
  34.  // concatenating the original item
  35.  // class name with "RefCntPtr"
  36.  #define RefCntPtr(type) \
  37.              type ## RefCntPtr
  38.  
  39.  
  40.  // If DEBUG is defined, using a zero
  41.  // pointer (an error) results in a
  42.  // message.  An exit() statement
  43.  // might also be appropriate.
  44.  
  45.  #ifdef DEBUG
  46.   #include <iostream.h>
  47.   #define RefCntPtrDebug(type)      \
  48.     if (0 == p_ptr)                 \
  49.       cout << "ERROR - using 0 "    \
  50.        "RefCntPtr to " #type "\n";
  51.  #else
  52.   #define RefCntPtrDebug(type)
  53.  #endif
  54.  
  55.  
  56.  #define RefCntPtrDECLARE(type)         \
  57.  class RefCntPtr(type)                  \
  58.   {                                     \
  59.    private:                             \
  60.                                         \
  61.     type * p_ptr;                       \
  62.                                         \
  63.     void p_inc (void);                  \
  64.                                         \
  65.     void p_decAndDelete (               \
  66.             type * dest);               \
  67.                                         \
  68.     void p_assign (                     \
  69.             type * rVal);               \
  70.    public:                              \
  71.     RefCntPtr(type) (void)              \
  72.       : p_ptr(0) {;};                   \
  73.                                         \
  74.     RefCntPtr(type) (                   \
  75.             const RefCntPtr(type)& in)  \
  76.       : p_ptr (in.p_ptr)                \
  77.       { p_inc(); };                     \
  78.                                         \
  79.     RefCntPtr(type) (                   \
  80.             type * in)                  \
  81.       : p_ptr(in)                       \
  82.       { p_inc(); };                     \
  83.                                         \
  84.     ~RefCntPtr(type) (void)             \
  85.       {p_decAndDelete(p_ptr);};         \
  86.                                         \
  87.     RefCntPtr(type) & operator = (      \
  88.             RefCntPtr(type) & rVal)     \
  89.       { p_assign (rVal.p_ptr);          \
  90.         return *this; };                \
  91.                                         \
  92.     RefCntPtr(type) & operator = (      \
  93.             type * rVal)                \
  94.       { p_assign (rVal);                \
  95.         return *this; };                \
  96.                                         \
  97.     type * operator -> (void)           \
  98.       { RefCntPtrDebug(type)            \
  99.         return p_ptr; };                \
  100.                                         \
  101.     type & operator * (void)            \
  102.       { RefCntPtrDebug(type)            \
  103.         return *p_ptr; };               \
  104.                                         \
  105.     /* see note */                      \
  106.     operator int (void)                 \
  107.       {return (p_ptr != 0);};           \
  108.                                         \
  109.    private:                             \
  110.     int operator == (RefCntPtr(type)&); \
  111.     int operator != (RefCntPtr(type)&); \
  112.     int operator <  (RefCntPtr(type)&); \
  113.     int operator <= (RefCntPtr(type)&); \
  114.     int operator >  (RefCntPtr(type)&); \
  115.     int operator >= (RefCntPtr(type)&); \
  116.  };
  117. // operator int() allows comparisons such as
  118. //   if (ptr) {},
  119. // which is great. Unfortunately, it also
  120. // allows comparisons such as
  121. //   if (ptr1 == ptr2) {}
  122. // to compile, but not as expected
  123. // - operator int() is first applied to
  124. // both sides, then the comparison is made
  125. // with the resulting integers.
  126. //
  127. // This behavior can be overridden by
  128. // declaring operator==  - it has precedence
  129. // here.  Since I am working in MS-DOS with
  130. // its segmented addressing, I didn't want
  131. // pointer comparisons, (they don't always
  132. // work) so I made operator== and its
  133. // companions private.  It would be simple
  134. // to make them public and implement them
  135. // if needed.
  136.  
  137.  
  138.  #define RefCntPtrDEFINE(type)             \
  139.  void RefCntPtr(type)::p_assign(           \
  140.          type * rVal)                      \
  141.                                            \
  142.  /* the order of the calls to the       */ \
  143.  /* increment and decrement functions   */ \
  144.  /* is significant here.  If the rVal   */ \
  145.  /* and current value point to the same */ \
  146.  /* place, we could delete the item and */ \
  147.  /* then discover we need it.           */ \
  148.   {                                        \
  149.    type * tmp = p_ptr;                     \
  150.    p_ptr = rVal;                           \
  151.    p_inc();                                \
  152.    p_decAndDelete(tmp);                    \
  153.   };                                       \
  154.                                            \
  155.  void RefCntPtr(type)::p_inc (void)        \
  156.   {                                        \
  157.    if (p_ptr)                              \
  158.      p_ptr->incRefCnt();                   \
  159.   };                                       \
  160.                                            \
  161.  void RefCntPtr(type)::p_decAndDelete (    \
  162.          type * dest)                      \
  163.   {                                        \
  164.    if (dest)                               \
  165.     {                                      \
  166.      dest->decRefCnt();                    \
  167.      if (0 == dest->refCnt())              \
  168.        delete dest;                        \
  169.     };                                     \
  170.   };
  171.  
  172. #endif
  173.